#include "stdafx.h"
#include "Variant.h"
#include <locale>

using namespace hc;

namespace 
{
	template<class CT,class fromCh,class toCh> 
	void cv_tool(CT ct, fromCh s1, fromCh s2, toCh d);

	template<> 
	void cv_tool(const std::ctype<wchar_t>* ct, const char* s1, const char* s2, wchar_t* d) 
	{ 
		ct->widen(s1,s2,d); 
	};

	template<> 
	void cv_tool(const std::ctype<wchar_t>* ct, const wchar_t* s1, const wchar_t* s2, char* d) 
	{ 
		ct->narrow(s1,s2,'?',d); 
	};

	template<
		class S,class E, class S_T=std::char_traits<S>,class S_A = std::allocator<S>,
		class SRC_STRING = basic_string<S,S_T,S_A>,
		class T = std::char_traits<E>,class A = std::allocator<E> >
	class str_cv: public std::unary_function<const SRC_STRING, std::basic_string<E, T, A> > 
	{ 
		std::locale loc_; 
		const std::ctype<wchar_t>* pCType_; 

		// No copy-constructor, no assignment operator... 
		str_cv(const str_cv&); 
		str_cv& operator= (const str_cv&); 

	public: 
		// Constructor... 
		str_cv(const std::locale& loc = std::locale()) : loc_(loc) 
		{ 
			pCType_ = &std::use_facet<std::ctype<wchar_t> >(loc); 
		} 

		// Conversion... 
		std::basic_string<E,T,A> operator() (const SRC_STRING& str) const 
		{ 
			typename SRC_STRING::size_type srcLen = str.length(); 
			const S* pSrcBeg = str.c_str();
			std::vector<E> tmp(srcLen); 
			cv_tool(pCType_,pSrcBeg, pSrcBeg + srcLen, &tmp[0]); 
			return std::basic_string<E,T,A>(&tmp[0], srcLen);
		} 
	};
}

wstring hc::wide_string(const string& s) 
{
	str_cv<char,wchar_t> to_wstr_converter;
	return to_wstr_converter(s);
} 
string hc::unwide_wstring(const wstring& s) 
{
	str_cv<wchar_t,char> to_str_converter;
	return to_str_converter(s);
} 

string hc::as_string(const _value_t& v) 
{
	stringstream sstr;
	
#define SUPPORT_TYPE(T)if(const T* p=boost::any_cast<T>(&v)) sstr << *p;
	
	SUPPORT_TYPE(int)
	else SUPPORT_TYPE(unsigned long)
	else SUPPORT_TYPE(bool)
	else if ( const string* p=boost::any_cast<string>(&v) ) sstr << *p;
	else if ( const wstring* p = boost::any_cast<wstring>(&v) ) sstr << hc::unwide_wstring(*p);
	else
		throw CException(ex_val("Unknown type",string(v.type().name())));

	return sstr.str();
}
	
wstring hc::as_wstring(const _value_t& v) 
{
	if ( const std::wstring* p = boost::any_cast<wstring>(&v) ) 
		return *p;
	return wide_string( as_string(v) );
}

